<template>
	<div class="search-div">
		<!-- 搜索表单 -->
		<el-form label-width="70px" size="small">
			<el-form-item label="角色名称">
				<el-input
					style="width: 100%"
					placeholder="角色名称"
					v-model="sysRoleDto.roleName"
				></el-input>
			</el-form-item>
			<el-row style="display:flex">
				<el-button type="primary" size="small" @click="fetchData">
					搜索
				</el-button>
				<el-button size="small" @click="reset">重置</el-button>
			</el-row>
		</el-form>

		<!-- 添加按钮 -->
		<div class="tools-div">
			<el-button type="success" size="small" @click="addShow">添 加</el-button>
		</div>


		<!-- 分配菜单的弹窗 -->
		<!-- props: 记录每个节点用于显示哪个属性，并且指定当前节点的下级列表对应的是哪个属性 { label:'title',children:'children' } -->
				  <!-- show-checkbox ,每个节点显示一个复选框 -->
				  <!-- 如果需要懒加载效果，此时需要这两个属性：:load="loadNode" lazy -->
				  <!-- show-checkbox 每个节点有一个复选框 -->
				  <!-- node-key="id" 指定每个节点的唯一键（回显时需要使用） -->
				  <!-- default-expand-all tree组件默认要展开 -->
				  <!-- :check-on-click-node="true"  默认只能点击复选框时，节点才会被选中；如果添加了这个属性，点击节点的任意位置都可以实现节点的选中 -->
				  <!-- ref="tree" ref绑定的对象，用于获取选中或者半选中状态的节点 -->
				  <!-- :data="sysMenuTreeList" 打开弹窗时，将后端返回的数据赋值给sysMenuTreeList -->
		<el-dialog
			v-model="assignMenuDialog"
			title="分配菜单"
			width="50%"
		> {{assignMenuDto}}
			<el-form label-width="70px" size="small">

				<el-row>
				   
				  <el-tree
				  	:data="sysMenuTreeList"
					:props="props"
					node-key="id"
					default-expand-all
					:check-on-click-node="true"
					show-checkbox
					ref="tree"
					@check-change="handleCheckChange"
				/>

				</el-row>

				<el-row style="display:flex">
					<el-button type="primary" size="small" @click="submitAssignMenu"  >
						提交
					</el-button>
				</el-row>
			</el-form>
			
		</el-dialog>

          
		<!-- dialogVisible变量=true，弹窗就被打开 -->
		<el-dialog
			v-model="dialogVisible"
			title="添加/修改"
			width="50%"
		>{{sysRole}}
			<el-form label-width="70px" size="small">
				<el-form-item label="角色名称">
					<el-input
						style="width: 100%"
						placeholder="角色名称"
						v-model="sysRole.roleName"
					></el-input>
				</el-form-item>
				<el-form-item label="角色编号">
					<el-input
						style="width: 100%"
						placeholder="角色编号"
						v-model="sysRole.roleCode"
					></el-input>
				</el-form-item>
				<el-form-item label="角色描述">
					<el-input
						style="width: 100%"
						placeholder="角色描述"
						v-model="sysRole.description"
					></el-input>
				</el-form-item>

				<el-row style="display:flex">
					<el-button type="primary" size="small" @click="submitDialog" >
						提交
					</el-button>
				</el-row>
			</el-form>
			
		</el-dialog>

		<!--- 角色表格数据 -->
		<el-table :data="list" style="width: 100%">
			<!-- roleName ，roleCode 。。。  json中的属性名 -->
			<el-table-column prop="roleName" label="角色名称" width="180" />
			<el-table-column prop="roleCode" label="角色code" width="180" />
			<el-table-column prop="createTime" label="创建时间" />
			<el-table-column label="操作" align="center" width="280" #default="scope">
				<el-button type="primary" size="small" @click="editShow(scope.row)">
					修改
				</el-button>
				<el-button type="danger" size="small" @click="deleteRole(scope.row.id)">
					删除
				</el-button>

				<!-- 参数：当前行角色的id -->
				<el-button type="warning" size="small" @click="showAssignMenuDialog(scope.row.id)">
					分配菜单
				</el-button>
			</el-table-column>
		</el-table>

		<!--分页条-->
		<el-pagination
			:page-sizes="[3, 5, 10, 100]"
			layout="total, sizes, prev, pager, next"
			:total="total"
			v-model:current-page="pageParam.pageNum"
			v-model:page-size="pageParam.pageSize"
			@size-change="fetchData"
			@current-change="fetchData"
		/>
	</div>
</template>

<script setup>
	import { ref, onMounted } from 'vue'
	import { FindByPage, DeleteById,AddRole,UpdateRole } from '@/api/sysRole'
	import { ElMessage,ElMessageBox } from 'element-plus'
	import { GetMenuListAndMenuIdList ,DoAssignMenu } from '@/api/sysMenu'

	// 分页条总记录数
	let total = ref(0)

	// 定义表格数据模型
	let list = ref([])

	// 定义了分页参数
	let pageParam = ref({
		pageNum: 1,
		pageSize: 3,
	})

	//条件查询的文本框绑定的属性
	let sysRoleDto = ref({
		roleName: '',
	})

	//钩子函数，自动调用
	onMounted(() => {
		fetchData()
	})

	//加载数据
	let fetchData = async () => {
		let { data } = await FindByPage(
			pageParam.value.pageNum,
			pageParam.value.pageSize,
			sysRoleDto.value
		)
		list.value = data.list
		total.value = data.total
	}

	//点击重置
	let reset = () => {
		pageParam.value.pageNum = 1
		pageParam.value.pageSize = 3
		sysRoleDto.value.roleName = ''
		fetchData()
	}

	//删除按钮绑定的方法
	let deleteRole =  id => {
		ElMessageBox.confirm('是否确定删除?', 'Warning', {
			confirmButtonText: '确定',
			cancelButtonText: '取消',
			type: 'warning',
		})
			.then(async () => {
				//确认框点击确定
				let { code } = await DeleteById(id)
				if (code == 200) {
					ElMessage.success('删除成功')
					fetchData()
				} else {
					ElMessage.warning('删除失败')
				}
			})
			.catch(() => {
				//确认框点击取消
				ElMessage({
					type: 'info',
					message: '取消删除',
				})
			})

		
	}

	//控制弹窗是否显示
	let dialogVisible = ref(false)

	//点击“添加”按钮要调用
	let addShow = ()=>{
		//每次打开弹窗，都先清除数据
		sysRole.value = {
			roleName:'',
			roleCode:'',
			description:''
		}
		dialogVisible.value = true
	}
	
	//弹窗上绑定的对象以及属性
	let sysRole = ref({
		roleName:'',
		roleCode:'',
		description:''
	})

	//点击弹窗上的提交按钮时(添加和修改，同一个提交按钮)
	let submitDialog = async ()=>{
	
		if(sysRole.value.id){
			//id不为空（修改）
			let {code,message} = await UpdateRole(sysRole.value)
			if(code==200){
				ElMessage.success('修改成功')
				dialogVisible.value = false
				fetchData()
			}else{
				ElMessage.warning('修改失败,' + message)
			}
		}else{
			//id为空（添加）
			let {code,message} = await AddRole(sysRole.value)
			if(code==200){
				ElMessage.success('添加成功')
				dialogVisible.value = false
				fetchData()
			}else{
				ElMessage.warning('添加失败,' + message)
			}
		}
	}

	//点击修改,回显数据
	let editShow = (row)=>{
		dialogVisible.value = true
		sysRole.value = row
	}

	//分配菜单弹窗
	let assignMenuDialog = ref(false)

	//分配菜单按钮
	let showAssignMenuDialog = (roleId)=>{

		//打开弹窗
		assignMenuDialog.value = true

		//清空dto
		assignMenuDto.value = {
			roleId:'',
			menuIdList:[]
		}

		fetchAssignMenuData(roleId)

		//为dto的roleId赋值
		assignMenuDto.value.roleId = roleId
	}

	//tree属性的第一个属性
	const props = {
		label: 'title', //tree节点显示的属性 {  id,parentId,title.. , children:[] }
		children: 'children',//指定该节点的子集合的属性名
	}

	//用于加载弹窗上的菜单列表，菜单id列表
	let fetchAssignMenuData =  async (roleId)=>{
		let {code,data} = await GetMenuListAndMenuIdList(roleId)
		if(code!=200){
			ElMessage.warning('弹窗数据加载失败')
			return
		}

		//从data中解析数据
		// console.log(data.menuList)
		// console.log(data.menuIdList)
		sysMenuTreeList.value = data.menuList 

		//tree.value.setCheckedKeys(data.roleMenuIds) 
		//tree是一个对象，被树组件去绑定了，通过tree对象设置哪些节点默认被选中，还可以获取选中和半选中状态的节点
		 tree.value.setCheckedKeys(data.menuIdList) //菜单id  哪些菜单id呢？

	}


	//定义tree组件绑定的对象
	let tree = ref()

	//后端接口返回的菜单列表，赋值给该集合
	let sysMenuTreeList = ref([])


	//定义分配菜单的参数
	let assignMenuDto = ref({
		roleId:'',
		menuIdList:[]
	})

	//分配菜单的提交按钮
	let submitAssignMenu = async ()=>{
		//获取所有选中状态的节点
		let checkedNodes = tree.value.getCheckedNodes();//【{}，{}】
		// console.log(checkedNodes)

		// checkedNodes.forEach(sysMenu => {
		// 	assignMenuDto.value.menuIdList.push({menuId:sysMenu.id,isHalf:0})
		// });

		//forEach 用于数组集合的遍历，没有返回值
		//map 也可以用于数组集合的遍历，有返回值

		//对菜单集合进行遍历，每个菜单对象转换成一个json对象（{menuId:sysMenu.id,isHalf:0}），map方法的返回值就是json集合
		let arr1 = checkedNodes.map(sysMenu=>{
			return {menuId:sysMenu.id,isHalf:0}
		})

		let halfCheckedNodes = tree.value.getHalfCheckedNodes()
		// halfCheckedNodes.forEach(sysMenu => {
		// 	assignMenuDto.value.menuIdList.push({menuId:sysMenu.id,isHalf:1})
		// });

		let arr2 = halfCheckedNodes.map(sysMenu=>{
			return {menuId:sysMenu.id,isHalf:1}
		})

		assignMenuDto.value.menuIdList = [...arr1,...arr2]; //两个json数组合并成一个json数组

		//调用后端接口
		let {code,message} = await DoAssignMenu(assignMenuDto.value)
		if(code==200){
			ElMessage.success('分配成功')
		}else{
			ElMessage.warning('分配失败,'+ message)
		}

		assignMenuDialog.value = false

	}

	

</script>

<style scoped>
	.search-div {
		margin-bottom: 10px;
		padding: 10px;
		border: 1px solid #ebeef5;
		border-radius: 3px;
		background-color: #fff;
	}

	.tools-div {
		margin: 10px 0;
		padding: 10px;
		border: 1px solid #ebeef5;
		border-radius: 3px;
		background-color: #fff;
	}
</style>